import { Service, Context } from 'egg';
const Crawler = require("crawler");

export class DetailsService extends Service {
    private crawler = new Crawler({
        // rateLimit: 2000,
        maxConnections: 50,
        // 在每个请求处理完毕后将调用此回调函数
        callback : async (error, res, done) => {
            const { app, ctx } = this;
            const model = app.model;
            if(error){
                await model.Lists.update({
                    error_message: String(error),
                    status: 'error',
                },
                {
                    where: {
                        id: res.options.id
                    }
                });
            }else{
                const $ = res.$;
                const data = {
                    list_id: res.options.id,
                    title: $('.d-brand-tit').text(),
                    description: $('.d-des-txt').text(),
                    status: $('#kaiyezhuangtai').text(),
                    brand_status: $('#Iszhaoshang').text(),
                };
                const map = {
                    '项目类型': 'type',
                    '开业时间': 'open_time',
                    '商业面积': 'area',
                    '商业楼层': 'floor',
                    '产品线项目': 'product_line',
                    '所在城市': 'city',
                    '项目地址': 'address',
                };
                const $status = $('.d-inf-status > li');
                $status.each(function (index) {
                    const $spans = $status.eq(index).find('span');
                    data[map[$spans.eq(0).text()]] = $spans.eq(1).text();
                });
                try {
                    await model.transaction(async transaction => {
                        await model.Lists.update({
                            status: 'success',
                        }, {
                            where: {
                                id: res.options.id
                            },
                            transaction,
                        });
                        await model.Details.create(data, {
                            transaction,
                        });
                    });
                } catch (err) {
                    ctx.throw(500, err.message);
                }
            }
            done();
        }
    });

    private queue: Array<any> = [];
    private total: number = 0;

    constructor (ctx: Context) {
        super(ctx);
        this.crawler.on('drain', () => {
            this.total += this.queue.length;
            if (this.queue.length > 0) {
                this.start();
            }
            console.log('======== finished ' + this.total + ' ========');
        })
    }
    
    public async start() {
        const { app } = this;
        const { model } = app;
        const lists = await model.Lists.findAll({
            where: {
                status: [ 'error', 'waiting' ],
            },
            attributes: [ 'id', 'url' ],
            limit: 1000,
        });
        this.queue = [];
        for (let i = 0; i < lists.length; i++) {
            const list = lists[i].get({
                plain: true,
            });
            this.queue.push({
                uri: list.url,
                id: list.id,
            });
        }
        this.crawler.queue(this.queue);

        return {
            status: 0,
            msg: 'success'
        }
    }
}

export default DetailsService;
